#include "sparrow.h"
#include "oled\oled.h"

#define NR_X	16
#define NR_Y	30

// 游戏常量定义
#define WIDTH  NR_X             // 游戏区域宽度
#define HEIGHT NR_Y             // 游戏区域高度
#define BLOCK_SIZE 4            // 方块矩阵大小
#define INIT_X (WIDTH/2 - 2)    // 初始位置X
#define INIT_Y 0                // 初始位置Y

// 游戏状态结构
typedef struct {
    uint16_t brd[HEIGHT];       // 游戏区域
    int curr_x, curr_y;   // 当前方块位置
    int current_type;           // 当前方块类型
    int curr_rot;       // 当前旋转状态
    int next_type;              // 下一个方块类型
    int score;                  // 当前分数
    int level;                  // 当前等级
    int lines_cleared;          // 已消除行数
    int game_over;              // 游戏结束标志
} GameState;

// 方块形状定义（7种形状，4种旋转）
const char shapes[7][4][4][4] = {
    // I
    {
     { { 0, 0, 0, 0}, { 1, 1, 1, 1}, { 0, 0, 0, 0}, { 0, 0, 0, 0}},
     { { 0, 0, 1, 0}, { 0, 0, 1, 0}, { 0, 0, 1, 0}, { 0, 0, 1, 0}},
     { { 0, 0, 0, 0}, { 0, 0, 0, 0}, { 1, 1, 1, 1}, { 0, 0, 0, 0}},
     { { 0, 1, 0, 0}, { 0, 1, 0, 0}, { 0, 1, 0, 0}, { 0, 1, 0, 0}}
      },
    // J
    {
     { { 1, 0, 0, 0}, { 1, 1, 1, 0}, { 0, 0, 0, 0}, { 0, 0, 0, 0}},
     { { 0, 1, 1, 0}, { 0, 1, 0, 0}, { 0, 1, 0, 0}, { 0, 0, 0, 0}},
     { { 0, 0, 0, 0}, { 1, 1, 1, 0}, { 0, 0, 1, 0}, { 0, 0, 0, 0}},
     { { 0, 1, 0, 0}, { 0, 1, 0, 0}, { 1, 1, 0, 0}, { 0, 0, 0, 0}}
      },
    // L
    {
     { { 0, 0, 1, 0}, { 1, 1, 1, 0}, { 0, 0, 0, 0}, { 0, 0, 0, 0}},
     { { 0, 1, 0, 0}, { 0, 1, 0, 0}, { 0, 1, 1, 0}, { 0, 0, 0, 0}},
     { { 0, 0, 0, 0}, { 1, 1, 1, 0}, { 1, 0, 0, 0}, { 0, 0, 0, 0}},
     { { 1, 1, 0, 0}, { 0, 1, 0, 0}, { 0, 1, 0, 0}, { 0, 0, 0, 0}}
      },
    // O
    {
     { { 0, 1, 1, 0}, { 0, 1, 1, 0}, { 0, 0, 0, 0}, { 0, 0, 0, 0}},
     { { 0, 1, 1, 0}, { 0, 1, 1, 0}, { 0, 0, 0, 0}, { 0, 0, 0, 0}},
     { { 0, 1, 1, 0}, { 0, 1, 1, 0}, { 0, 0, 0, 0}, { 0, 0, 0, 0}},
     { { 0, 1, 1, 0}, { 0, 1, 1, 0}, { 0, 0, 0, 0}, { 0, 0, 0, 0}}
      },
    // S
    {
     { { 0, 1, 1, 0}, { 1, 1, 0, 0}, { 0, 0, 0, 0}, { 0, 0, 0, 0}},
     { { 0, 1, 0, 0}, { 0, 1, 1, 0}, { 0, 0, 1, 0}, { 0, 0, 0, 0}},
     { { 0, 0, 0, 0}, { 0, 1, 1, 0}, { 1, 1, 0, 0}, { 0, 0, 0, 0}},
     { { 1, 0, 0, 0}, { 1, 1, 0, 0}, { 0, 1, 0, 0}, { 0, 0, 0, 0}}
      },
    // T
    {
     { { 0, 1, 0, 0}, { 1, 1, 1, 0}, { 0, 0, 0, 0}, { 0, 0, 0, 0}},
     { { 0, 1, 0, 0}, { 0, 1, 1, 0}, { 0, 1, 0, 0}, { 0, 0, 0, 0}},
     { { 0, 0, 0, 0}, { 1, 1, 1, 0}, { 0, 1, 0, 0}, { 0, 0, 0, 0}},
     { { 0, 1, 0, 0}, { 1, 1, 0, 0}, { 0, 1, 0, 0}, { 0, 0, 0, 0}}
      },
    // Z
    {
     { { 1, 1, 0, 0}, { 0, 1, 1, 0}, { 0, 0, 0, 0}, { 0, 0, 0, 0}},
     { { 0, 0, 1, 0}, { 0, 1, 1, 0}, { 0, 1, 0, 0}, { 0, 0, 0, 0}},
     { { 0, 0, 0, 0}, { 1, 1, 0, 0}, { 0, 1, 1, 0}, { 0, 0, 0, 0}},
     { { 0, 1, 0, 0}, { 1, 1, 0, 0}, { 1, 0, 0, 0}, { 0, 0, 0, 0}}
      }
};

GameState g_game;

void set_brd(GameState * gs, int y, int x, int v)
{
    if (v)
        gs->brd[y] |= (1 << x);
    else
        gs->brd[y] &= ~(1 << x);
}

int get_brd(GameState * gs, int y, int x)
{
    return (gs->brd[y] & (1 << x)) != 0;
}

// 初始化游戏
void init_game(GameState * game)
{
    // 清空游戏区域
    for (int y = 0; y < HEIGHT; y++) {
        game->brd[y] = 0;
    }

    // 初始化游戏状态
    game->curr_x = INIT_X;
    game->curr_y = INIT_Y;
    game->curr_rot = 0;
    game->score = 0;
    game->level = 1;
    game->lines_cleared = 0;
    game->game_over = 0;

    // 随机生成当前和下一个方块
    spr_srand(spr_get_ms());
    game->current_type = spr_rand() % 7;
    game->next_type = spr_rand() % 7;
}

// 绘制游戏区域
void draw_board(GameState * game)
{
    // 绘制游戏区域边框
    for (int y = 0; y < HEIGHT; y++) {
        for (int x = 0; x < WIDTH; x++) {
            // 绘制游戏区域内的方块
            oled_change_blk(x, y, get_brd(game, y, x));
        }
    }

    // 绘制当前方块
    for (int y = 0; y < BLOCK_SIZE; y++) {
        for (int x = 0; x < BLOCK_SIZE; x++) {
            if (shapes[game->current_type][game->curr_rot][y][x]) {
                oled_change_blk(game->curr_x + x, game->curr_y + y, 1);
            }
        }
    }
    oled_refresh();
}

// 检查位置是否有效
int is_valid_position(GameState * game, int x, int y, int rotation)
{
    for (int py = 0; py < BLOCK_SIZE; py++) {
        for (int px = 0; px < BLOCK_SIZE; px++) {
            if (shapes[game->current_type][rotation][py][px]) {
                int board_x = x + px;
                int board_y = y + py;

                // 检查是否超出边界
                if (board_x < 0 || board_x >= WIDTH || board_y >= HEIGHT) {
                    return 0;
                }

                // 检查是否与已有方块重叠
                if (board_y >= 0 && get_brd(game, board_y, board_x)) {
                    return 0;
                }
            }
        }
    }
    return 1;
}

// 旋转当前方块
void rotate_current(GameState * game)
{
    int new_rotation = (game->curr_rot + 1) % 4;

    if (is_valid_position(game, game->curr_x, game->curr_y, new_rotation)) {
        // 擦除原位置方块
        for (int y = 0; y < BLOCK_SIZE; y++) {
            for (int x = 0; x < BLOCK_SIZE; x++) {
                if (shapes[game->current_type][game->curr_rot][y][x]) {
                    oled_change_blk(game->curr_x + x, game->curr_y + y, 0);
                }
            }
        }

        game->curr_rot = new_rotation;

        // 绘制新位置方块
        for (int y = 0; y < BLOCK_SIZE; y++) {
            for (int x = 0; x < BLOCK_SIZE; x++) {
                if (shapes[game->current_type][game->curr_rot][y][x]) {
                    oled_change_blk(game->curr_x + x, game->curr_y + y, 1);
                }
            }
        }
    }
    oled_refresh();
}

// 移动当前方块
int move_current(GameState * game, int dx, int dy)
{
    int new_x = game->curr_x + dx;
    int new_y = game->curr_y + dy;

    if (is_valid_position(game, new_x, new_y, game->curr_rot)) {
        // 擦除原位置方块
        for (int y = 0; y < BLOCK_SIZE; y++) {
            for (int x = 0; x < BLOCK_SIZE; x++) {
                if (shapes[game->current_type][game->curr_rot][y][x]) {
                    oled_change_blk(game->curr_x + x, game->curr_y + y, 0);
                    spr_printf("old: x=%x, y=%x, v=0\n", game->curr_x + x, game->curr_y + y);
                }
            }
        }

        game->curr_x = new_x;
        game->curr_y = new_y;

        // 绘制新位置方块
        for (int y = 0; y < BLOCK_SIZE; y++) {
            for (int x = 0; x < BLOCK_SIZE; x++) {
                if (shapes[game->current_type][game->curr_rot][y][x]) {
                    oled_change_blk(game->curr_x + x, game->curr_y + y, 1);
                    spr_printf("new: x=%x, y=%x, v=1\n", game->curr_x + x, game->curr_y + y);
                }
            }
        }

        oled_refresh();
        return 1;
    }
    return 0;
}

// 固定当前方块到游戏区域
void lock_piece(GameState * game)
{
    for (int y = 0; y < BLOCK_SIZE; y++) {
        for (int x = 0; x < BLOCK_SIZE; x++) {
            if (shapes[game->current_type][game->curr_rot][y][x]) {
                int board_x = game->curr_x + x;
                int board_y = game->curr_y + y;

                if (board_y >= 0) {
                    set_brd(game, board_y, board_x, 1);
                }
            }
        }
    }
}

// 检查并消除完整行
int clear_lines(GameState * game)
{
    int lines_cleared = 0;

    for (int y = HEIGHT - 1; y >= 0; y--) {
        int line_full = 1;

        // 检查行是否完整
        for (int x = 0; x < WIDTH; x++) {
            if (!get_brd(game, y, x)) {
                line_full = 0;
                break;
            }
        }

        if (line_full) {
            lines_cleared++;

            // 擦除该行
            for (int x = 0; x < WIDTH; x++) {
                set_brd(game, y, x, 0);
                oled_change_blk(x, y, 0);
            }

            // 将上面的行下移
            for (int yy = y; yy > 0; yy--) {
                for (int x = 0; x < WIDTH; x++) {
                    int v;
                    v = get_brd(game, yy - 1, x);
                    set_brd(game, yy, x, v);
                    oled_change_blk(x, yy, v);
                }
            }

            // 清空最顶行
            for (int x = 0; x < WIDTH; x++) {
                set_brd(game, 0, x, 0);
                oled_change_blk(x, 0, 0);
            }

            // 因为行下移了，需要重新检查当前行
            y++;
        }
    }

    return lines_cleared;
}

// 生成新方块
void new_piece(GameState * game)
{
    game->current_type = game->next_type;
    game->next_type = spr_rand() % 7;
    game->curr_x = INIT_X;
    game->curr_y = INIT_Y;
    game->curr_rot = 0;

    // 检查游戏是否结束
    if (!is_valid_position(game, game->curr_x, game->curr_y, game->curr_rot)) {
        game->game_over = 1;
    }
}

// 更新分数
void update_score(GameState * game, int lines)
{
    // 根据消除的行数计算分数
    int points = 0;
    switch (lines) {
    case 1:
        points = 100;
        break;
    case 2:
        points = 300;
        break;
    case 3:
        points = 500;
        break;
    case 4:
        points = 800;
        break;
    }

    game->score += points * game->level;
    game->lines_cleared += lines;

    // 每清除8行升一级
    game->level = (game->lines_cleared>>3) + 1;
}

// 游戏主循环
void tetris_game_loop(void)
{
    uint32_t t0, t1;

    uint32_t fall_timer = 0;
    uint32_t fall_delay = 500;       // 初始下落延迟（毫秒）

    uint32_t dip;

    init_game(&g_game);

    t0 = spr_get_ms();
    while (!g_game.game_over) {

        dip = spr_get_dip_b();
        LED_B = dip;
        dip = spr_get_dip_c();
        LED_C = dip;
 
        int key = spr_get_ch();

        // 处理按键输入
        if (key != -1) {
            switch (key) {
            case 'h':          // 左移
                move_current(&g_game, -1, 0);
                break;
            case 'l':          // 右移
                move_current(&g_game, 1, 0);
                break;
            case 'j':          // 加速下落
                if (move_current(&g_game, 0, 1)) {
                    fall_timer = 0; // 重置计时器
                }
                break;
            case ' ':          // 旋转
                rotate_current(&g_game);
                break;
            case 'a':          // 硬下落（直接落到底）
                while (move_current(&g_game, 0, 1)) {
                    // 绘制每一步
                    draw_board(&g_game);
                }
                fall_timer = 0; // 重置计时器
                break;
            case 'q':          // 退出游戏
                return;
            }
        }

        t1 = spr_get_ms();

        if (t0 == t1)
            continue;

        fall_timer += (t1 - t0);
        t0 = t1;

        // 方块自动下落
        if (fall_timer >= fall_delay) {
            if (!move_current(&g_game, 0, 1)) {
                // 无法下落，固定方块
                lock_piece(&g_game);

                // 检查并消除完整行
                int lines = clear_lines(&g_game);
                if (lines > 0) {
                    update_score(&g_game, lines);
                }

                // 生成新方块
                new_piece(&g_game);
            }
            fall_timer = 0;     // 重置计时器

            // 根据等级调整下落速度
            fall_delay = 1000 - (g_game.level - 1) * 100;
            if (fall_delay < 100)
                fall_delay = 100;
        }

        // 绘制游戏状态
        draw_board(&g_game);
    }

    // 游戏结束处理
    // 这里可以添加游戏结束的显示逻辑
}



